use std::{
    sync::Arc,
    // time::Duration
};

use chrono::{TimeZone, Local};
use prisma_client_rust::{QueryError, WhereQuery, Direction};
use serde::{Serialize, Deserialize};
use rspc::{Type};
use crate::prisma::{PrismaClient, meeting};
use uuid::Uuid;

#[derive(Clone, Serialize, Deserialize, Type, Debug)]
pub struct CreateMeetingData {
    pub uuid: Option<String>,
    pub slug: String,
    pub started_at: String,
    pub time: String,
    pub presenter: String,
    pub types: String,
    pub members: String,
    pub outline: Option<String>,
    pub attachment: Option<String>,
    pub status: String
}

#[derive(Clone, Serialize, Deserialize, Type, Debug)]
pub struct  DeleteMeeting {
    pub uuid: String
}

#[derive(Clone, Serialize, Deserialize, Type, Debug)]
pub struct MeetingParams {
    pub slug: Option<String>,
    pub types: Option<String>,
    pub state: Option<String>
}

pub struct MeetingManager {

}

impl MeetingManager {
    pub async fn get(client: Arc<PrismaClient>, args: MeetingParams) -> Result<Vec<crate::prisma::meeting::Data>, QueryError> {
        let mut query = client
            .meeting()
            .find_many(vec![
                meeting::slug::contains(args.slug.unwrap().to_string()),
            ]);

        if !args.types.is_none() {
            query
                .add_where(meeting::types::equals(args.types.unwrap().to_string()))
        }

        if !args.state.is_none() {
            query
                .add_where(meeting::state::equals(Some(args.state.unwrap().to_string())))
        }

        Ok(
            query
                .order_by(meeting::created_at::order(Direction::Desc))
                .exec()
                .await?
        )
    }

    pub async fn delete(client: Arc<PrismaClient>, args: DeleteMeeting) -> Result<(), QueryError> {
        let _ = client
            .meeting()
            .delete(meeting::uuid::equals(args.uuid.to_string()))
            .exec()
            .await?;
        Ok(())
    }

    pub async fn save(client: Arc<PrismaClient>, args: CreateMeetingData) -> Result<(), QueryError> {
        println!("{:?}", args);
        let uuid = if args.uuid.is_none() {
            Uuid::new_v4().clone().to_string()
        } else {
            args.uuid.clone().unwrap().to_string()
        };
        println!("{:?}", uuid);

        let started_at = Local.datetime_from_str(&args.started_at, "%Y-%m-%d %H:%M:%S");
        println!("{:?}", started_at.unwrap());
        let _ = client
            .meeting()
            .upsert(
                meeting::uuid::equals(uuid.clone().to_string()),
                // uuid, slug, started_at, presenter, types, members, mut _params
                (
                    uuid.clone().to_string(),
                    args.slug.clone(),
                    started_at.unwrap().into(),
                    args.time.clone(),
                    args.presenter.clone(),
                    args.types.clone(),
                    args.members.clone(),
                    vec![
                        meeting::outline::set(Some(args.outline.clone().unwrap().to_string())),
                        meeting::attachment::set(Some(args.attachment.clone().unwrap().to_string())),
                        meeting::created_at::set(Local::now().into()),
                        meeting::status::set(Some(args.status.clone().to_string()))
                    ]
                ),
                vec![
                    meeting::slug::set(args.slug.clone()),
                    meeting::started_at::set(started_at.unwrap().into()),
                    meeting::time::set(args.time.clone()),
                    meeting::presenter::set(args.presenter.clone()),
                    meeting::types::set(args.types.clone()),
                    meeting::members::set(args.members.clone()),
                    meeting::updated_at::set(Some(Local::now().into())),
                    meeting::outline::set(Some(args.outline.clone().unwrap().to_string())),
                    meeting::attachment::set(Some(args.attachment.clone().unwrap().to_string())),
                    meeting::created_at::set(Local::now().into()),
                    meeting::status::set(Some(args.status.clone().to_string()))
                ]
            )
            .exec()
            .await;

        // std::thread::sleep(Duration::from_secs(3));
        return Ok(());
    }
}
